function gadget:GetInfo()
  return {
    name      = "Switch Weapon",
    desc      = "Adds a button to unit that allows to switch between its weapons",
    author    = "Rafal",
    date      = "Mar 2011",
    license   = "GNU GPL, v2 or later",
    layer     = 0,
    enabled   = true  --  loaded by default?
  }
end

--------------------------------------------------------------------------------
--------------------------------------------------------------------------------

if (not gadgetHandler:IsSyncedCode()) then
  return
end
-- SYNCED

--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- CONFIG

local units = {
  "weapons_platform",
}

--------------------------------------------------------------------------------

VFS.Include("LuaRules/Configs/custom_cmds.lua")

local max = math.max
local spGetGameFrame = Spring.GetGameFrame
local spGetUnitWeaponState = Spring.GetUnitWeaponState
local spSetUnitWeaponState = Spring.SetUnitWeaponState
local spInsertUnitCmdDesc = Spring.InsertUnitCmdDesc
local spFindUnitCmdDesc = Spring.FindUnitCmdDesc
local spEditUnitCmdDesc = Spring.EditUnitCmdDesc
local spGetUnitDefID = Spring.GetUnitDefID

--------------------------------------------------------------------------------

local switchWeaponCmd = {
      id      = CMD_DEBUG_SWITCH_WEAPON,
      name    = "switchWeapon",
      action  = "switchWeapon",
      type    = CMDTYPE.ICON_MODE,
      tooltip = "Switch to next weapon",
      params  = { 0 }
}

local BIG_NUMBER = 9999999
local defsToParams = {}
local unitData = {}


for _, unitName in ipairs(units) do
  local ud = UnitDefNames[unitName]
  if (not ud) then
    Spring.Echo('[unit_switch_weapon.lua] Error: No UnitDef of name "' .. unitName .. '"')
  elseif (not defsToParams[ud.id]) then
    if (#ud.weapons < 2) then
      Spring.Echo('[unit_switch_weapon.lua] Error: UnitDef "' .. unitName .. '" has only ' .. #ud.weapons .. ' weapons (must have at least 2 to switch)')
    else
      local weapons = ud.weapons
      local params = { 0, "All weapons" }
      for i = 1, #weapons do
        local wdID = weapons[i].weaponDef
        params[i + 2] = string.sub("[" .. i .. "] " .. WeaponDefs[wdID].description, 1, 15)
      end
      defsToParams[ud.id] = params
    end  
  end  
end

local function StopWeapon(unitID, weaponNum)
  local reloadFrame = spGetUnitWeaponState(unitID, weaponNum - 1, "reloadFrame")
  if (reloadFrame ~= BIG_NUMBER) then
    unitData[unitID].reloadTimeLeft[weaponNum] = max(0, reloadFrame - spGetGameFrame())
    spSetUnitWeaponState(unitID, weaponNum - 1, {reloadState = BIG_NUMBER})
  end  
end

--------------------------------------------------------------------------------
--------------------------------------------------------------------------------

function gadget:Initialize()
	local units = Spring.GetAllUnits()
	for i = 1, #units do
		local udID = spGetUnitDefID(units[i])
		gadget:UnitCreated(units[i], udID)  --, nil, -1)
	end
end

function gadget:UnitCreated(unitID, unitDefID, unitTeam, builderID)
  if (defsToParams[unitDefID]) then
    switchWeaponCmd.params = defsToParams[unitDefID]
    spInsertUnitCmdDesc(unitID, 12, switchWeaponCmd)
    unitData[unitID] = {
      currentWeapon = 0,  --All weapons
      reloadTimeLeft = {},
    }
  end
end

function gadget:UnitDestroyed(unitID, unitDefID, unitTeam)
  unitData[unitID] = nil
end

function gadget:AllowCommand(unitID, unitDefID, teamID, cmdID, cmdParams, cmdOptions, cmdTag, synced)
  if (cmdID == CMD_DEBUG_SWITCH_WEAPON and unitData[unitID]) then
    local numWeapons = #UnitDefs[unitDefID].weapons
    local data = unitData[unitID]
    local oldWeapon = data.currentWeapon
    if (cmdOptions.right) then
      cmdParams[1] = (oldWeapon > 0) and oldWeapon - 1 or numWeapons
    end
    local newWeapon = cmdParams[1]
    
    if (newWeapon ~= oldWeapon) then
      switchWeaponCmd.params = defsToParams[unitDefID]
      switchWeaponCmd.params[1] = cmdParams[1]
      spEditUnitCmdDesc(unitID, spFindUnitCmdDesc(unitID, CMD_DEBUG_SWITCH_WEAPON), switchWeaponCmd)
      switchWeaponCmd.params[1] = 0
 
      if (oldWeapon == 0) then 
        for i = 1, numWeapons do
          if (i ~= newWeapon) then
            StopWeapon(unitID, i)
          end
        end
      elseif (newWeapon ~= 0) then
        StopWeapon(unitID, oldWeapon)       
      end   

      data.currentWeapon = newWeapon
    
      if (newWeapon == 0) then
        local reloadTimeLeft = data.reloadTimeLeft
        for i = 1, numWeapons do
          if (i ~= oldWeapon) then
            spSetUnitWeaponState(unitID, i - 1, 
              {reloadState = spGetGameFrame() + reloadTimeLeft[i]}) 
          end
        end
      elseif (oldWeapon ~= 0) then 
        spSetUnitWeaponState(unitID, newWeapon - 1, 
          {reloadState = spGetGameFrame() + data.reloadTimeLeft[newWeapon]}) 
      end
    end        
    return false  --so the command called without shift doesn't eat command queue  
  end
  return true
end

-- SYNCED